package com.hancher.common.androidutil;

import java.util.concurrent.TimeUnit;

import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
import io.reactivex.rxjava3.core.FlowableTransformer;
import io.reactivex.rxjava3.core.Observable;
import io.reactivex.rxjava3.core.ObservableOnSubscribe;
import io.reactivex.rxjava3.core.ObservableTransformer;
import io.reactivex.rxjava3.core.Observer;
import io.reactivex.rxjava3.disposables.Disposable;
import io.reactivex.rxjava3.functions.Action;
import io.reactivex.rxjava3.functions.Consumer;
import io.reactivex.rxjava3.schedulers.Schedulers;

/**
 * 作者：Hancher
 * 时间：2020/2/1.
 * 邮箱：ytu_shaoweijie@163.com
 * 版本：v1.0
 * <p>
 * 说明：
 */
public class AsyncUtils {
    private static final String runStart = "异步任务开始>>>";
    private static final String runEnd = "异步任务完成<<<";
    private static final boolean isLogEnd = false;

    /**
     * 废弃：异步执行任务
     *
     * @param observable 被观察者
     * @param observer   观察者（内涵四个方法）
     */
    public static <T> void run(ObservableOnSubscribe<T> observable, Observer<T> observer) {
        Observable.create(observable)
                .compose(getThreadTransformer())
                .subscribe(observer);
    }

    /**
     * 异步任务
     *
     * @param observable 可观察的量
     * @param onNext     消费
     * @param <T>        中间量类型
     * @return 一次性销毁
     */
    public static <T> Disposable run(ObservableOnSubscribe<T> observable,
                                     Consumer<? super T> onNext) {
        return run(observable,
//                (disposable) -> LogUtil.v(runStart),
                onNext,
                () -> {
                    if (isLogEnd)
                        LogUtil.v(runEnd);
                },
                LogUtil::e);
    }

    /**
     * 异步任务
     *
     * @param observable 可观察的量
     * @param onNext     消费
     * @param onError    异常
     * @param <T>        中间量类型
     * @return 一次性销毁
     */
    public static <T> Disposable run(ObservableOnSubscribe<T> observable,
                                     Consumer<? super T> onNext,
                                     Consumer<? super Throwable> onError) {
        return run(observable,
//                (disposable) -> LogUtil.v(runStart),
                onNext,
                () -> {
                    if (isLogEnd)
                        LogUtil.v(runEnd);
                },
                onError);
    }

    /**
     * 异步任务
     *
     * @param observable  可观察的量
     * @param onNext      消费
     * @param onCompletes 结束
     * @param onError     异常
     * @param <T>         中间量类型
     * @return 一次性销毁
     */
    public static <T> Disposable run(ObservableOnSubscribe<T> observable,
                                     Consumer<? super T> onNext,
                                     Action onCompletes,
                                     Consumer<? super Throwable> onError) {
        return Observable.create(observable)
                .compose(getThreadTransformer())
                .subscribe(onNext, onError, onCompletes);
    }

//    /**
//     * 异步任务 显示等待弹窗 建议超过2s的异步使用
//     * @param observable 可观察的量
//     * @param onNext 消费
//     * @return 一次性销毁
//     * @param <T> 中间量类型
//     */
//    public static <T> Disposable runWithWaitDialog(ObservableOnSubscribe<T> observable,
//                                                   Consumer<? super T> onNext){
//        WaitDialog dialog = WaitDialog.show("请稍后...");
//        return Observable.create(observable)
//                .compose(getThreadTransformer())
//                .subscribe(onNext, throwable -> {
//                    if (dialog != null && dialog.isShow()) {
//                        dialog.doDismiss();
//                    }
//                }, () -> {
//                    if (dialog != null && dialog.isShow()) {
//                        dialog.doDismiss();
//                    }
//                });
//    }

    /**
     * 倒计时1次
     *
     * @param millis      延迟
     * @param onCompletes 完成
     */
    public static void runCountdownOnce(Long millis, Action onCompletes) {
        /**
         * start：起始数值
         * count：发射数量
         * initialDelay：延迟执行时间
         * period：发射周期时间
         * unit：时间单位
         */
        Observable.intervalRange(0, 1, millis, millis, TimeUnit.MILLISECONDS)
                .compose(getThreadTransformer())
                .subscribe(aLong -> {
                }, LogUtil::e, onCompletes);
    }

    /**
     * 倒计时
     *
     * @param start       开始值
     * @param count       个数
     * @param delay       延迟
     * @param period      间隔周期
     * @param onNext      下一步
     * @param onCompletes 完成
     * @return 取消
     */
    public static Disposable runCountdown(Long start, Long count, Long delay, Long period,
                                          Consumer<? super Long> onNext, Action onCompletes) {

        return Observable.intervalRange(start, count, delay, period, TimeUnit.MILLISECONDS)
                .compose(getThreadTransformer())
                .subscribe(onNext, LogUtil::e, onCompletes);
    }

    /**
     * 倒计时
     *
     * @param start       开始值
     * @param count       个数
     * @param delay       延迟
     * @param period      间隔周期
     * @param onCompletes 完成
     * @return Disposable
     */
    public static Disposable runCountdown(Long start, Long count, Long delay, Long period,
                                          Action onCompletes) {
        /**
         * start：起始数值
         * count：发射数量
         * initialDelay：延迟执行时间
         * period：发射周期时间
         * unit：时间单位
         */
        return Observable.intervalRange(start, count, delay, period, TimeUnit.MILLISECONDS)
                .compose(getThreadTransformer())
                .subscribe(aLong -> LogUtil.d("onNext:" + aLong), LogUtil::e, onCompletes);
    }

    /**
     * 异步执行心跳任务
     *
     * @param millis 心跳周期
     * @param onNext 下一步
     */
    public static void runHeartbeat(Long millis, Consumer<Long> onNext) {
        Observable.interval(0, millis, TimeUnit.MILLISECONDS)
                .compose(getThreadTransformer())
                .subscribe(onNext, LogUtil::e);
    }

    /**
     * 可观察子线程，观察者主线程
     * 用来代替 <br/>
     * .subscribeOn(Schedulers.io()) <br/>
     * .observeOn(AndroidSchedulers.mainThread()) <br/>
     *
     * @param <T> 实体类内容
     * @return ObservableTransformer
     */
    public static <T> ObservableTransformer<T, T> getThreadTransformer() {
        return upstream -> upstream.subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread());
    }

    public static <T> FlowableTransformer<T, T> getFlowableTransformer() {
        return upstream -> upstream.subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread());
    }
}
